package main

import (
	"fmt"
	"math"
	"strconv"
)

type Elem string

const STACK_SIZE int = 9

type stack struct {
	size, cur int
	top       *node
}

type node struct {
	data Elem
	next *node
}

func newStack(size int) (s *stack) {
	s = new(stack)
	s.size = size
	s.cur = 0
	return
}

func (s *stack) push(data Elem) {
	if s.cur < s.size {
		s.top = &node{data, s.top}
		s.cur++
	} else {
		fmt.Printf("full stack,%v\n", data)
	}
}

func (s *stack) pop() (data Elem) {
	if s.cur >= 1 {
		data = s.top.data
		s.top = s.top.next
		s.cur--
	} else {
		fmt.Printf("no data \n")
	}
	return
}

func (s *stack) empty() {
	head := s.top
	for {
		if s.top.next == nil {
			s.top = head
			break
		}
		s.top = s.top.next
	}
	s.cur = 0
}

func (s *stack) to10() (result float64) {
	size := s.cur
	for i := 1; i <= size; i++ {
		tmp, _ := strconv.Atoi(string(s.pop()))
		fmt.Printf("%d", tmp)
		result += float64(tmp) * math.Pow(2, float64(i-1))
	}
	return

}

func (s *stack) String() (str string) {
	head := s.top
	for i := 1; i <= s.cur; i++ {
		str += string(s.top.data + "->")
		s.top = s.top.next
	}
	str = str + " size:" + strconv.Itoa(s.cur)
	s.top = head
	return str
}

func main() {
	s := newStack(STACK_SIZE)
	s.push("a")
	s.push("b")
	s.push("c")
	s.push("d")
	s.push("e")
	s.push("f")
	s.push("g")
	s.push("h")
	s.push("i")
	s.push("j")
	s.push("m")
	fmt.Printf("%v\n", s)

	data := s.pop()
	fmt.Printf("pop data:%v\n", data)
	s.push("s")
	fmt.Printf("%v\n", s)

	s.empty()
	fmt.Printf("after empty %v\n", s)

	s.push("1")
	s.push("0")
	s.push("1")
	s.push("1")
	fmt.Printf("after init bin %v\n", s)
	fmt.Printf("to10 :%f", s.to10())

}
